namespace MessageBroker.Client

import System
import System.Collections
import MessageBroker

class BrokerClient:
"""Description of Client"""

	[property(Server)]
	server as IBroker

	[property(InstanceName)]
	instanceName as string
	
	[property(MessagesPerPage)]
	messagesPerPage as int
	
	[property(LocalQueue)]
	localQueue = Queue()
	
	[property(UseBufferedSending)]
	useBufferedSending=false
	
	[getter(SentMessagesCount)]
	private sentMessagesCount as int

	[getter(ReceivedMessagesCount)]
	private receivedMessagesCount as int

	[property(PollEvery)]
	private pollEvery as int = 10

	private isListening = false
	
	def constructor():
		pass
		
	private def PrepareMessage(queueName as string, message as Message):
		message.Id = "${instanceName}_${sentMessagesCount++}"
		message.SentTo=queueName
		message.TimeStamp=DateTime.Now
		message.SentFrom = instanceName

	def SendImmediately(queueName as string, message as Message):
		PrepareMessage(queueName, message)
		server.Send(queueName, message)

	def Send(queueName as string, message as Message):
		PrepareMessage(queueName, message)
		if not useBufferedSending:
			server.Send(queueName, message)
		else:
			add2LocalQueue(queueName, message)

	private def add2LocalQueue(queueName as string, message as Message):
		lock localQueue:
			localQueue.Enqueue(message)
		CheckLocalQueue()
		
	private def CheckLocalQueue():
		if (localQueue.Count>= messagesPerPage):
			Flush()
			
	def Flush():
		lock localQueue:
			messages = List()
			for n in range(localQueue.Count):
				msg2send = localQueue.Dequeue() as Message
				messages.Add(msg2send)
		server.MassiveSend(messages, instanceName)

	def AsyncFlush():
		lock localQueue:
			messages = List()
			for n in range(localQueue.Count):
				msg2send = localQueue.Dequeue() as Message
				messages.Add(msg2send)
		server.MassiveSend.BeginInvoke(messages, instanceName)
		
	private def countAndReturn(result as IList) as IList:
		if result != null: receivedMessagesCount += result.Count
		return result
		
	private def countAndReturn(result as Message) as Message:
		if result != null: receivedMessagesCount += 1
		return result
		
	def	Receive(queueName as string) as Message:
		return countAndReturn(server.Receive(queueName, instanceName))

	def	Receive(queueName as string, howMany as int) as Message:
		return countAndReturn(server.Receive(queueName, instanceName, howMany))
		
	def	Receive(howMany as int) as IList:
		return countAndReturn(server.Receive(instanceName, howMany))

	def	BufferedReceive(queueName as string) as IList:
		return countAndReturn(server.Receive(queueName, instanceName, messagesPerPage))

	def	BufferedReceive() as IList:
		return countAndReturn(server.Receive(instanceName, messagesPerPage))

	event ReceivedMessages as callable(IList)
	
	private def pollForMessages(): 
		while isListening:
			msgs = BufferedReceive()
			if msgs != null and msgs.Count > 0: 
				ReceivedMessages(msgs)
			System.Threading.Thread.Sleep(pollEvery)
	
	def Listen():
		isListening = true
		pollForMessages.BeginInvoke()
		
	def Cancel():
		isListening = false
